using System;
using System.Collections;
using Cinemachine;
using Unity.VisualScripting;
using UnityEngine;

public class Bullet : BulletBase
{
    private enum State
    {
        Targeting = 0,
        Deflected = 1,
        HasCutEnemy = 2,
        Impaled = 3
    }

    [SerializeField]
    private float defaultRadius;

    [SerializeField]
    private float mass;

    [SerializeField]
    private float guide;

    [SerializeField]
    private float life;

    [SerializeField]
    private float speed;

    [SerializeField]
    private float rotationPerSecond;

    [SerializeField]
    private float separatingForce;

    [SerializeField]
    private float particleCountPerSec;

    [SerializeField]
    private float particleEmitRadius;

    [SerializeField]
    private float particleRadius;

    [SerializeField]
    private int hitParticleCount;

    [SerializeField]
    private float hitParticleRadius;

    [SerializeField]
    private float hitParticleVelocityFactor;

    [SerializeField]
    private float accelSmoothing;//加速平滑

    [SerializeField]
    private float damageFactor;

    [SerializeField]
    private float deflectThreshold;//偏转阈值

    [SerializeField]
    private float forceFactorForCut;

    [SerializeField]
    private float forceFactorForDeflect;

    [SerializeField]
    private float forceFactorForImpale;

    [SerializeField]
    private Color32 hitParticleColor;

    [SerializeField]
    private MeshFilter meshFilter;

    [SerializeField]
    private Collider collider;

    private State state;

    private EnemyPart target;

    private Vector3 localTargetPoint;

    private float time;

    private Vector3 velocity;

    private Vector3 smoothedAccel;

    private Vector3 angularVelocity;

    private float particleTimer;

    private ParticleRenderer particleRenderer;

    private Vector3 impaledPosition;

    private Quaternion impaledRotation;

    private Transform impaledTransform;

    private EnemyPart impaledPart;

    public override GameObject GameObject => null;

    public override Color FlyParticleColor => default(Color);

    public override float DefaultRadius => 0f;

    public override float SeparatingForce => 0f;

    public override bool Alive => false;

    public override Vector3 Position => default(Vector3);

    public override Vector3 Velocity => default(Vector3);

    public override float Damage => 0f;

    public override Vector3 Impulse => default(Vector3);

    public override bool Targeting => false;

    public override EnemyPart ImpaledPart => null;

    public override bool Impaled => false;
    public ParticleSystem particleSystem1;
    public ParticleSystem particleSystem2;
    public CinemachineImpulseSource impulseSource;
    public override void Kill()
    {
        OnKilled?.Invoke(this);
        PoolManager.Instance.Free(PoolType.Thrown, gameObject);
    }

    public override Vector3 GetTargetPoint()
    {
        if (target != null)
        {
            return target.transform.position + localTargetPoint - transform.position;
        }
        else
        {
            return velocity;
        }
    }

    public override Mesh CreateMesh(float outerRadius, float innerRadius, float holeRadius, float thickness)
    {
        return null;
    }
    Vector3 myNormal;
    float damageMul = 1f;
    public override void ManualStart(EnemyPart target, Vector3 localTargetPoint, Vector3 upVector, Vector3 gunPoint, Vector3 initialDirection, ParticleRenderer particleRenderer, Mesh mesh, float scale)
    {
        if (scale < 0.2f)
        {
            particleSystem1.Stop();
        }
        this.target = target;
        this.localTargetPoint = localTargetPoint;
        this.particleRenderer = particleRenderer;
        myNormal = upVector;
        transform.position = gunPoint;
        transform.rotation = Quaternion.LookRotation(initialDirection, upVector);
        collider.enabled = true;
        state = State.Targeting;
        time = 0f;
        velocity = initialDirection;
        smoothedAccel = Vector3.zero;
        angularVelocity = Vector3.zero;
        targetPoint = GetTargetPoint();
        direction = targetPoint.normalized;
        transform.localScale = new Vector3(0.5f, 0.1f, 0.5f) * Mathf.Clamp(scale, 0f, 0.8f + Main.Instance.saveData.SizeLevel * 0.02f);
        damageMul = scale * (0.8f + Main.Instance.saveData.PowerLevel * 0.02f);
        isFristTrigger = true;
        speed += Main.Instance.saveData.SpeedLevel * 0.1f;
    }
    Vector3 targetPoint;
    Vector3 direction;
    public override void ManualFixedUpdate(float deltaTime)
    {
        if (state == State.Impaled)
        {
            transform.SetParent(impaledTransform, true);
            return;
        }
        if (state == State.Targeting && target != null)
        {
            targetPoint = GetTargetPoint();
            direction = targetPoint.normalized;
            Vector3 guideForce = CalcGuideForce();
            Vector3 acceleration = guideForce / mass;
            smoothedAccel = Vector3.Lerp(smoothedAccel, acceleration, accelSmoothing * deltaTime);
            velocity += smoothedAccel * deltaTime;
            velocity = Vector3.ClampMagnitude(velocity, speed);
            direction = velocity;
        }
        else if (state == State.Deflected)
        {
            direction = velocity.normalized;
        }
        else if (state == State.HasCutEnemy)
        {
            direction = velocity.normalized;
        }
        float moveStep = speed * deltaTime;
        Vector3 newPosition = transform.position + direction * moveStep;
        transform.position = newPosition;
        meshFilter.transform.Rotate(Vector3.up, rotationPerSecond * deltaTime * 360, Space.Self);
        time += deltaTime;
        if (time > 5f)
        {
            Kill();
        }
    }
    public override float SimulateError(Vector3 firePoint, Vector3 initialDirection, Vector3 targetPoint, Vector3 targetVelocity, int iteration)
    {
        return 0f;
    }

    public override void ManualUpdate(float deltaTime)
    {
    }

    public override Plane GetPlane()
    {
        return default(Plane);
    }

    public override void OnHitUnbreakable(Vector3 normal)
    {
        Vector3 bounceDirection = Vector3.Reflect(velocity.normalized, normal);
        velocity = bounceDirection * (velocity.magnitude * bounceSpeedReduction);
        transform.rotation = Quaternion.LookRotation(velocity.normalized, myNormal);
        state = State.Deflected;
    }

    public override void OnHitEnemy(out float forceFactorOut, out Enemy.DamageType damageTypeOut, float damageRatio, Transform targetTransform, Vector3 normal, EnemyPart part)
    {
        if (part.isDeflected && UnityEngine.Random.Range(0.0f, 1f) < (part.Deflectprobability - Main.Instance.saveData.PenetrateLevel * 0.02f))
        {
            damageTypeOut = Enemy.DamageType.Deflect;
            forceFactorOut = forceFactorForDeflect;
            state = State.Deflected;
            velocity = -velocity + Vector3.one * (Mathf.Sign(UnityEngine.Random.Range(-1f, 1f)) * UnityEngine.Random.Range(0.5f, 1f));
            transform.rotation = Quaternion.LookRotation(velocity.normalized, myNormal);
            AudioManager.Instance.PlayOnShot((int)ClipType.jinshupengzhuang);
        }
        else
        {
            part.Damage(this, damageFactor * damageRatio * damageMul, out EnemyPart newSubPart);
            if (part.Hp <= 0)
            {
                state = State.HasCutEnemy;
                forceFactorOut = forceFactorForCut;
                damageTypeOut = Enemy.DamageType.Cut;
                part.PostDamage(this, damageFactor * damageRatio * damageMul, damageTypeOut);
                AudioManager.Instance.PlayOnShot((int)ClipType.qiege);
                collider.enabled = false;
                part.Cut(this);
            }
            else
            {
                state = State.Impaled;
                forceFactorOut = forceFactorForImpale;
                damageTypeOut = Enemy.DamageType.Impale;
                impaledPart = part;
                impaledPosition = part.transform.InverseTransformPoint(transform.position);
                impaledRotation = Quaternion.Inverse(part.transform.rotation) * transform.rotation;
                impaledTransform = part.transform;
                particleSystem1.Stop();
                particleSystem2.Play();
                collider.enabled = false;
                StartCoroutine(Imaple());
            }
            if (part.Hp <= 0 || damageMul > 0.5f)
            {
                if (impulseSource != null)
                {
                    impulseSource.GenerateImpulseWithForce(0.25f);
                }
            }
        }
        Main.Instance.OnHitEnemy(damageMul, damageTypeOut);
    }
    IEnumerator Imaple()
    {
        yield return null;
        AudioManager.Instance.PlayOnShot((int)ClipType.ciru);
        state = State.Impaled;
    }
    private Vector3 CalcGuideForce()
    {
        if (target == null || state != State.Targeting)
            return Vector3.zero;

        Vector3 worldTargetPoint = target.transform.TransformPoint(localTargetPoint);

        // 调用静态方法计算制导力
        return CalcGuideForce(
            p: transform.position,
            v: velocity,
            targetPoint: worldTargetPoint,
            guide: this.guide
        );
    }

    private static Vector3 CalcGuideForce(Vector3 p, Vector3 v, Vector3 targetPoint, float guide)
    {
        float distanceToTarget = Vector3.Distance(p, targetPoint);
        float timeToTarget = distanceToTarget / v.magnitude;
        Vector3 predictedTargetPos = targetPoint + v.normalized * timeToTarget;
        Vector3 desiredDirection = (predictedTargetPos - p).normalized;
        Vector3 steeringForce = (desiredDirection - v.normalized) * guide;
        float maxSteeringForce = 0.5f;
        if (steeringForce.magnitude > maxSteeringForce)
        {
            steeringForce = steeringForce.normalized * maxSteeringForce;
        }

        return steeringForce;
    }

    private void UpdateParticle(ParticleRenderer particleRenderer, float deltaTime)
    {
    }

    private static int AddQuad(int[] indices, int offset, int i0, int i1, int i2, int i3)
    {
        return 0;
    }

    private static int AddQuadRev(int[] indices, int offset, int i0, int i1, int i2, int i3)
    {
        return 0;
    }
    bool isFristTrigger = true;
    [SerializeField]
    private float bounceForceFactor = 1.0f;
    [SerializeField]
    private float bounceSpeedReduction = 0.7f;
    [SerializeField]
    private int maxBounceCount = 3;
    private void OnTriggerEnter(Collider otherCollider)
    {
        if (otherCollider.transform.GetComponent<Unbreakable>() != null)
        {
            OnHitUnbreakable(otherCollider.transform.up);
            return;
        }
        if (!isFristTrigger) return;
        if (otherCollider.transform.parent.TryGetComponent<EnemyPart>(out EnemyPart enemyPart))
        {
            Vector3 normal = Vector3.zero;
            Ray ray = new Ray(transform.position, direction);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, direction.magnitude * 2))
            {
                // 获取精确的法线
                normal = hit.normal;
            }
            Debug.DrawRay(ray.origin, ray.direction * 100, Color.blue, 5f);
            OnHitEnemy(out float forceFactorOut, out Enemy.DamageType damageTypeOut, damageFactor, otherCollider.transform, normal, enemyPart);
            isFristTrigger = false;
        }

    }
}